package com.agrm.rabc.service.impl;

import com.agrm.model.rabc.dto.*;
import com.agrm.rabc.service.*;
import com.agrm.utils.XinUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class RbacServiceImpl implements RbacService {
    private UserGroupMappingService userGroupMappingService;
    private GroupRoleMappingService groupRoleMappingService;
    private RolePermMappingService rolePermMappingService;
    private PermResourceMappingService permResourceMappingService;
    private GroupService groupService;
    private RoleService roleService;
    private PermService permService;
    private ResourceService resourceService;
    private MenuService menuService;

    @Autowired
    public void setUserGroupMappingService(UserGroupMappingService userGroupMappingService) {
        this.userGroupMappingService = userGroupMappingService;
    }

    @Autowired
    public void setGroupRoleMappingService(GroupRoleMappingService groupRoleMappingService) {
        this.groupRoleMappingService = groupRoleMappingService;
    }

    @Autowired
    public void setRolePermMappingService(RolePermMappingService rolePermMappingService) {
        this.rolePermMappingService = rolePermMappingService;
    }

    @Autowired
    public void setPermResourceMappingService(PermResourceMappingService permResourceMappingService) {
        this.permResourceMappingService = permResourceMappingService;
    }

    @Autowired
    public void setGroupService(GroupService groupService) {
        this.groupService = groupService;
    }

    @Autowired
    public void setRoleService(RoleService roleService) {
        this.roleService = roleService;
    }

    @Autowired
    public void setPermService(PermService permService) {
        this.permService = permService;
    }

    @Autowired
    public void setResourceService(ResourceService resourceService) {
        this.resourceService = resourceService;
    }

    @Autowired
    public void setMenuService(MenuService menuService) {
        this.menuService = menuService;
    }

    //查询指定用户的所有角色
    @Override
    public List<Role> findAllRolesByUserId(Integer userId) {
        List<Role> roles = new ArrayList<>();
        UserGroupMapping search = new UserGroupMapping();
        search.setUserId(userId);
        List<UserGroupMapping> mappings = userGroupMappingService.findAll(search);

        GroupRoleMapping grm = new GroupRoleMapping();
        for (UserGroupMapping ugm : mappings) {
            Integer groupId = ugm.getGroupId();//组编号
            grm.setGroupId(groupId);

            List<GroupRoleMapping> mappings1 = groupRoleMappingService.findAll(grm);
            for (GroupRoleMapping gr : mappings1) {
                Integer roleId = gr.getRoleId();
                Role role = roleService.findById(roleId);
                if (role != null) {//角色可用
                    roles.add(role);
                }
            }
        }
        return roles;
    }

    //查询指定用户的所有可用角色
    @Override
    public List<Role> findValidRolesByUserId(Integer userId) {
        List<Role> roles = new ArrayList<>();
        UserGroupMapping search = new UserGroupMapping();
        search.setUserId(userId);
        List<UserGroupMapping> mappings = userGroupMappingService.findAll(search);

        GroupRoleMapping grm = new GroupRoleMapping();
        for (UserGroupMapping ugm : mappings) {
            Integer groupId = ugm.getGroupId();//组编号
            Group group = groupService.findById(groupId);

            if (group != null && group.getEnabled()) {//组可用
                grm.setGroupId(groupId);
                List<GroupRoleMapping> mappings1 = groupRoleMappingService.findAll(grm);
                for (GroupRoleMapping gr : mappings1) {
                    Integer roleId = gr.getRoleId();
                    Role role = roleService.findById(roleId);
                    if (role != null && role.getEnabled()) {
                        roles.add(role);
                    }
                }
            }
        }
        return roles;
    }

    //查询指定用户所有权限
    @Override
    public List<Perm> findAllPermsByUserId(Integer userId) {
        List<Perm> perms = new ArrayList<>();
        List<Role> roles = findAllRolesByUserId(userId);

        RolePermMapping rpm = new RolePermMapping();
        for (Role role : roles) {
            rpm.setRoleId(role.getId());
            List<RolePermMapping> mappings = rolePermMappingService.findAll(rpm);
            for (RolePermMapping rp : mappings) {
                Integer permId = rp.getPermId();//权限编号
                Perm perm = permService.findById(permId);
                if (perm != null) {
                    perms.add(perm);
                }
            }
        }
        return perms;
    }

    //查询指定用户所有可用权限
    @Override
    public List<Perm> findValidPermsByUserId(Integer userId) {
        List<Perm> perms = new ArrayList<>();
        List<Role> roles = findValidRolesByUserId(userId);//所有可用角色

        RolePermMapping rpm = new RolePermMapping();
        for (Role role : roles) {
            rpm.setRoleId(role.getId());

            List<RolePermMapping> mappings = rolePermMappingService.findAll(rpm);
            for (RolePermMapping rp : mappings) {
                Integer permId = rp.getPermId();//权限编号
                Perm perm = permService.findById(permId);
                if (perm != null && perm.getEnabled()) {//权限可用
                    perms.add(perm);
                }
            }
        }
        return perms;
    }

    //查询所有资源-权限映射关系
    @Override
    public Map<Resource, List<Perm>> findAllResourcePermMappings() {
        Map<Resource, List<Perm>> map = new HashMap<>();

        PermResourceMapping prm = new PermResourceMapping();
        //查询所有权限-资源对应
        List<PermResourceMapping> mappings = permResourceMappingService.findAll(prm);
        for (PermResourceMapping pr : mappings) {
            Integer permId = pr.getPermId();//权限编号
            Integer resourceId = pr.getResourceId();//资源编号

            Perm p = permService.findById(permId);//权限实体
            Resource r = resourceService.findById(resourceId);//资源实体

            List<Perm> perms = map.get(r);//有可能为空

            if (perms == null) {
                perms = new ArrayList<>();
                perms.add(p);
                map.put(r, perms);
            } else {
                perms.add(p);
            }
        }
        return map;
    }

    //查询指定用户的所有菜单
    @Override
    public List<Menu> findAllMenusByUserId(Integer userId) {
        //查询所有可用权限
        List<Perm> validPerms = findValidPermsByUserId(userId);
        List<Resource> resources = new ArrayList<>();

        PermResourceMapping search = new PermResourceMapping();
        for (Perm perm : validPerms) {
            search.setPermId(perm.getId());
            List<PermResourceMapping> mappings = this.permResourceMappingService.findAll(search);
            mappings.forEach(it -> resources.add(it.getResource()));
        }

        List<Resource> list = resources.stream().filter(it -> it.getType().equals("菜单")).toList();

        List<Menu> rtn = new ArrayList<>();
        for (Resource res : list) {
            String value = res.getValue();//资源值
            String[] menuIdArr = value.split(",");
            for (String menuId : menuIdArr) {
                Menu menu = this.menuService.findById(Integer.valueOf(menuId));
                rtn.add(menu);
            }
        }

        //将菜单树化，并排序
        return treeify(rtn);
    }

    //将菜单树化，并排序
    private List<Menu> treeify(List<Menu> treeMenus) {
        Map<Integer, Menu> cache = new HashMap<>();
        List<Menu> roots = new ArrayList<>();
        for (Menu menu : treeMenus) {
            if (menu.getParent() == null) {//根节点
                roots.add(menu);
            } else {
                Menu parent = cache.get(menu.getParentId());
                if (parent != null) {
                    parent.getChildren().add(menu);
                    menu.setParent(parent);
                } else {
                    while (menu.getParent() != null) {
                        parent = menu.getParent();//父菜单
                        parent.setChildren(new ArrayList<>());
                        parent.getChildren().add(menu);//仅添加当前子菜单
                        cache.put(parent.getId(), parent);
                        menu = parent;
                    }
                    roots.add(menu);
                }
            }
        }
        //对菜单进行排序
        sort(roots);
        return roots;
    }

    //对菜单进行排序
    private void sort(List<Menu> menus) {
        menus.stream().filter(it-> XinUtils.isNotEmpty(it.getChildren())).forEach(it->sort(it.getChildren()));
        menus.sort(Comparator.comparingInt(Menu::getSort));
    }
}
